﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.Core;
using Domain.MainModule.Entities;
using Domain.MainModule.Employees;
using Domain.Core.Specification;

namespace Application.MainModule.EmployeesManagement
{
    public class EmployeeManagementService: IEmployeeManagementService, IDisposable
    {

        #region Members

        IEmployeeRepository _EmployeeRepository;

        #endregion

        #region Constructor

        /// <summary>
        /// Default constructor for EmployeeService
        /// </summary>
        /// <param name="employeeRepository">EmployeeRepository dependency, usually this is resolver with IoC</param>
        public EmployeeManagementService(IEmployeeRepository employeeRepository)
        {
            if (employeeRepository == (IEmployeeRepository)null)
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);

            _EmployeeRepository = employeeRepository;
        }

        #endregion

        public void AddEmployee(Employee employee)
        {
            if (employee.UserId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidUserId, "employee.UserId");

            IUnitOfWork unitOfWork = _EmployeeRepository.UnitOfWork as IUnitOfWork;
            _EmployeeRepository.Add(employee);
            unitOfWork.Commit();
        }

        public void ChangeEmployee(Employee employee)
        {
            IUnitOfWork unitOfWork = _EmployeeRepository.UnitOfWork as IUnitOfWork;
            _EmployeeRepository.Modify(employee);
            unitOfWork.CommitAndRefreshChanges();
        }

        public void RemoveEmployee(Employee employee)
        {
            if (employee == (Employee)null)
                throw new ArgumentNullException("employee");

            IUnitOfWork unitOfWork = _EmployeeRepository.UnitOfWork as IUnitOfWork;
            employee.IsEnabled = false;
            _EmployeeRepository.Modify(employee);
            unitOfWork.CommitAndRefreshChanges();
        }

        public Employee FindEmplyeeByMembershipUserId(Guid userId)
        {
            if (userId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidUserId, "userId");

            EmployeeMembershipUserIdSpecification spec = new EmployeeMembershipUserIdSpecification(userId);
            return _EmployeeRepository.FindEmployee(spec);
        }

        public Employee FindEmplyeeByBranchId(Guid branchId)
        {
            if (branchId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidBranchId, "branchId");

            EmployeeBranchSpecification spec = new EmployeeBranchSpecification(branchId);
            return _EmployeeRepository.FindEmployee(spec);
        }

        public Employee FindEmployeeById(Guid userId)
        {
            if (userId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidBranchId, "userId");

            EmployeeUserIdSpecification spec = new EmployeeUserIdSpecification(userId);
            return _EmployeeRepository.FindEmployee(spec);
        }

        #region IDisposable

        /// <summary>
        /// Dispose associated context with this domain service
        /// </summary>
        public void Dispose()
        {
            if (_EmployeeRepository != null
                &&
                _EmployeeRepository.UnitOfWork != null)
            {
                _EmployeeRepository.UnitOfWork.Dispose();
            }
        }

        #endregion

        public List<Employee> FindPagedEmployees(int pageIndex, int pageCount)
        {
            if (pageIndex < 0)
                throw new ArgumentException(Resources.Messages.exception_InvalidPageIndex, "pageIndex");

            if (pageCount <= 0)
                throw new ArgumentException(Resources.Messages.exception_InvalidPageCount, "pageCount");

            bool enabled = true;
            Specification<Employee> onlyEnabledSpec = new DirectSpecification<Employee>(c => c.IsEnabled == enabled);

            return _EmployeeRepository.GetPagedElements(pageIndex, pageCount, c => c.LastName, onlyEnabledSpec, true).ToList();

        }
    }
}
